#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <unistd.h>
#include "Task.hpp"

using namespace std;

const int gnum=5; //创建的管道数目
Task t;

class EndPoint  //子进程和管道对应起来
{
    public:
    pid_t _child_id; //子进程的pid
    int _write_fd; //对应的管道
    public:
    EndPoint(int id,int fd) //构造函数
    :_child_id(id)
    ,_write_fd(fd)  //初始化列表
    {
    }
    ~EndPoint()
    {

    }
};

//子进程要执行的方法
void WaitCommand()
{
    while(true)
    {
        int command=0;
        int n=read(0,&command,sizeof(int));
        if(n==sizeof(int))
        {
            t.Execute(command);
        }
        else if(n==0)
        {
            break;
        }
        else{
            break;
        }
    }
}

void creatProcess(vector<EndPoint>* end_points) 
{
    for(int i=0;i<gnum;i++)
    {
        //1.1创建管道
        int pipefd[2]={0};
        int n=pipe(pipefd);
        assert(n==0);
        (void) n;

        //1.2创建子进程
        pid_t id=fork();
        assert(id!=-1);
        //一定是子进程
        if(id==0)
        {
            //1.3关闭不要的fd
            close(pipefd[1]);
        //期望，所有的子进程读取"指令"的时候，都从标准输入读取
            // 1.3.1 输入重定向
        dup2(pipefd[0],0);
        //1.3.2 子进程开始等待获取命令
        WaitCommand();
        close(pipefd[0]);
        exit(0);
        }

        //一定是父进程
        //1.3关闭不要的fd
        close(pipefd[0]);

        //1.4将新的子进程和它的管道写端，构建对象
        end_points->push_back(EndPoint(id,pipefd[1]));
    }
}

int main()
{
    //1.先进行构建控制结构，父进程写入，子进程读取
    vector<EndPoint> end_points;
    creatProcess(&end_points);
    //2.我们得到了 end_points,就是一个关于子进程和管道对应关系的数组
    int num=0;

    while(true)
    {
        //1.选择任务
        int command=COMMAND_LOG;
        //2.选择进程
        int index=rand()%end_points.size();
        //3.下发任务
        write(end_points[index]._write_fd,&command,sizeof(command));

        sleep(1);
    }
    return 0;
}